home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / network / file-tra / fsp-2.7 / fsp-2 / fsp / client / util.c < prev   
Encoding:
C/C++ Source or Header  |  1993-05-21  |  13.9 KB  |  589 lines

  1.  /*********************************************************************\
  2.  *  Copyright (c) 1991 by Wen-King Su (wen-king@vlsi.cs.caltech.edu)   *
  3.  *                                                                     *
  4.  *  You may copy or modify this file in any manner you wish, provided  *
  5.  *  that this notice is always included, and that you hold the author  *
  6.  *  harmless for any loss or damage resulting from the installation or *
  7.  *  use of this software.                                              *
  8.  \*********************************************************************/
  9.  
  10. #include "tweak.h"
  11. #include "client_def.h"
  12. #include "c_extern.h"
  13.  
  14. #ifndef VMS
  15. extern char *realloc(), *malloc(), *getenv();
  16. #endif
  17. extern long atol();
  18. extern int errno;
  19.  
  20. static int env_dir_malloced = 0;
  21. char *env_dir = "/";
  22. char *env_passwd = "\0";
  23. char *env_myport;
  24. char *env_host;
  25. char *env_port;
  26. char *env_local_dir;
  27. int env_timeout;
  28. unsigned short client_buf_len;
  29. unsigned short client_net_len;
  30.  
  31. char *util_abs_path PROTO1(char *, s2)
  32. {
  33.   char *path, *s, *d, *t;
  34.   
  35.   if(!env_dir) env_dir = "";
  36.   if(!s2) s2 = "";
  37.   
  38.   if(*s2 == '/') {
  39.     path = malloc(strlen(s2)+2+strlen(env_passwd)+1);
  40.     sprintf(path,"/%s",s2);
  41.   } else {
  42.     path = malloc(strlen(env_dir)+strlen(s2)+3+strlen(env_passwd)+1);
  43.     sprintf(path,"/%s/%s",env_dir,s2);
  44.   }
  45.   
  46.   for(t = path; *t; ) {
  47.     if(t[0] == '/') {
  48.       while(t[1] == '/') for(d = t, s = t+1; *d++ = *s++; );
  49.       if(t != path && t[1] == 0) { t[0] = 0; return(path); }
  50.     }
  51.     if(t[0] == '.' && t[1] == '.') {
  52.       if(t-1 == path && t[2] ==  0 ) {
  53.     *t = 0;
  54.     return(path);
  55.       }
  56.       if(t-1 == path && t[2] == '/') {
  57.     for(d = t, s = t + 3; *d++ = *s++; );
  58.     continue;
  59.       }
  60.       if(t[-1] == '/' && (t[2] == '/' || t[2] ==  0)) {
  61.     s = t + 2; /* point to either slash or nul */
  62.     t -= 2;    /* guaranteed that t >= path here */
  63.     while(t > path && t[0] != '/') t--;
  64.     if(t != path || *s == '/') for(d = t; *d++ = *s++; );
  65.     else {
  66.       t[1] = 0;
  67.       return(path);
  68.     }
  69.     continue;
  70.       }
  71.     }
  72.     if(t[0] == '.') {
  73.       if(t-1 == path && t[1] ==  0 ) {
  74.     *t = 0;
  75.     return(path);
  76.       }
  77.       if(t-1 == path && t[1] == '/') {
  78.     for(d = t, s = t + 2; *d++ = *s++; );
  79.     continue;
  80.       }
  81.       if(t[-1] == '/' && (t[1] == '/' || t[1] ==  0)) {
  82.     s = t + 1; /* point to either slash or nul */
  83.     for(d = t-1; *d++ = *s++; ); 
  84.     t--;
  85.     continue;
  86.       }
  87.     }
  88.     t++;
  89.   }
  90.   return(path);
  91. }
  92.  
  93. char *util_getwd PROTO1(char *, p)
  94. {
  95.   if(p) strcpy(p,env_dir);
  96.   return(p);
  97. }
  98.  
  99. static RDIRENT **get_dir_blk PROTO1(char *, path)
  100. {
  101.   RDIRENT **dp;
  102.   char *p1, *p2, *fpath, buf[2*UBUF_SPACE];
  103.   unsigned long pos;
  104.   int cnt, k, len, rem, acc, at_eof, rlen;
  105.   UBUF *ub;
  106.   
  107.   fpath = util_abs_path(path);
  108.   
  109.   for(pos = 0, at_eof = acc = cnt = 0; ; ) {
  110.     while((acc < UBUF_SPACE) && !at_eof) {
  111.       ub = client_interact(CC_GET_DIR,pos, strlen(fpath),
  112.                (unsigned char *)fpath+1, 2,
  113.                (unsigned char *)&client_net_len);
  114.       
  115.       if(ub->cmd == CC_ERR) {
  116.     fprintf(stderr,"%s: %s\n",path, ub->buf);
  117.     free(fpath);
  118.     errno = EACCES;
  119.     return((RDIRENT **) 0);
  120.       }
  121.  
  122.       rlen = BB_READ2(ub->bb_len);
  123.       if(rlen < client_buf_len) at_eof = 1;
  124.       for(p1 = ub->buf, p2 = buf + acc, k = rlen; k--; ) *p2++ = *p1++;
  125.       acc += rlen;
  126.       pos += rlen;
  127.     }
  128.       
  129.     if(acc >= UBUF_SPACE) len = UBUF_SPACE;
  130.     else len = acc;
  131.       
  132.     for(p2 = buf, rem = len, k = 0; ; k++) {
  133.       if(rem < RDHSIZE) break;
  134.       if(((RDIRENT *) p2)->type == RDTYPE_SKIP) break;
  135.       if(((RDIRENT *) p2)->type == RDTYPE_END ) { k++; break; }
  136.       p2 += RDHSIZE; rem -= (RDHSIZE+1);
  137.       while(*p2++) rem--;
  138.       while((p2 - buf) & 3) {
  139.     p2++;
  140.     rem--;
  141.       }
  142.     }
  143.       
  144.     p1 = malloc(p2-buf);
  145.     if(cnt) dp = (RDIRENT **) realloc(dp,(cnt+k+1)*sizeof(RDIRENT *));
  146.     else dp = (RDIRENT **)  malloc((cnt+k+1)*sizeof(RDIRENT *));
  147.       
  148.     if(!p1 || !dp) {
  149.       free(fpath);
  150.       fputs("directory reading out of memory\n",stderr);
  151.       return((RDIRENT **) 0);
  152.     }
  153.       
  154.     for(p2 = buf, rem = len; ; cnt++) {
  155.       if(rem < RDHSIZE) break;
  156.       if(((RDIRENT *) p2)->type == RDTYPE_SKIP) break;
  157.       if(((RDIRENT *) p2)->type == RDTYPE_END) {
  158.     dp[cnt] = 0;
  159.     return(dp);
  160.       }
  161.       dp[cnt] = (RDIRENT *) p1;
  162.       
  163.       for(k = RDHSIZE, rem -= (RDHSIZE+1); k--; *p1++ = *p2++);
  164.       while(*p1++ = *p2++) rem--;
  165.       while((p2 - buf) & 3) {
  166.     p2++;
  167.     p1++;
  168.     rem--;
  169.       }
  170.     }
  171.       
  172.     if(acc < UBUF_SPACE) {
  173.       dp[cnt] = 0;
  174.       return(dp);
  175.     }
  176.     for(p1 = buf + UBUF_SPACE, p2 = buf, k = (acc -= UBUF_SPACE); k--;)
  177.       *p2++ = *p1++;
  178.   }
  179. }
  180.  
  181. static int util_download_main PROTO5(char *, path, char *, fpath, FILE *, fp,
  182.                      unsigned long, start_from, int, cmd)
  183. {   
  184.   unsigned long pos, started_from = start_from, downloaded;
  185.   unsigned tmax, wrote, sent_time, rlen;
  186.   UBUF *ub;
  187.   time_t t = time(NULL);
  188.   
  189.   for(tmax = 1, pos = start_from, sent_time = 0; ;) {   
  190.     ub = client_interact(cmd,pos,strlen(fpath),(unsigned char *)fpath+1, 2,
  191.              (unsigned char *)&client_net_len);
  192.       
  193.     if(client_trace && (udp_sent_time != sent_time)) {
  194.       sent_time = udp_sent_time;
  195.       if(client_buf_len == UBUF_SPACE) fprintf(stderr,"\r%luk  ",1+(pos>>10));
  196.       else fprintf(stderr,"\r%lu   ", pos);
  197.       fflush(stderr);
  198.     }
  199.       
  200.     if(ub->cmd == CC_ERR) {    
  201.       fprintf(stderr,"downloading %s: %s\n",path,ub->buf);
  202.       return(-1); 
  203.     }
  204.       
  205.     rlen = BB_READ2(ub->bb_len);
  206.     wrote = fwrite(ub->buf,1,rlen,fp);
  207.     pos  += wrote;
  208.       
  209.     if(rlen < client_buf_len || rlen != wrote) break;
  210.   }
  211.   
  212.   t = time(NULL) - t;
  213.   if (t == 0) t = 1;
  214.   downloaded = pos - started_from;
  215.   if(client_trace) {
  216.     fprintf(stderr,"\r%luk : %s [%db/s] \n", 1+(pos>>10), path, downloaded/t);
  217.     fflush(stderr);
  218.   }
  219.   
  220.   return(0);
  221. }
  222.  
  223. int util_download PROTO3(char *, path, FILE *, fp, unsigned long, start_from)
  224. {   
  225.   int code, len;
  226.   char *fpath;
  227.   
  228.   fpath = util_abs_path(path);
  229.   if(*env_passwd) {
  230.     strcat(fpath, "\n");
  231.     strcat(fpath, env_passwd);
  232.     len = strlen(fpath);
  233.   }
  234.   code = util_download_main(path, fpath, fp, start_from, CC_GET_FILE);
  235.   free(fpath);
  236.   return(code);
  237. }
  238.  
  239. int util_grab_file PROTO3(char *, path, FILE *, fp, unsigned long, start_from)
  240. {   
  241.   int code, len;
  242.   char *fpath;
  243.   UBUF *ub;
  244.   
  245.   fpath = util_abs_path(path);
  246.   if(*env_passwd) {
  247.     strcat(fpath, "\n");
  248.     strcat(fpath, env_passwd);
  249.     len = strlen(fpath);
  250.   }
  251.   code = util_download_main(path, fpath, fp, start_from, CC_GRAB_FILE);
  252.   if(code) {
  253.     free(fpath);
  254.     return(code);
  255.   }
  256.   
  257.   ub = client_interact(CC_GRAB_DONE, 0L, len, (unsigned char *)fpath+1, 0,
  258.                (unsigned char *)NULLP);    
  259.   
  260.   if(ub->cmd == CC_ERR) {
  261.     fprintf(stderr,"Warning, unexpected grab error: %s\n",ub->buf);
  262.   }
  263.   
  264.   free(fpath);
  265.   return(code);
  266. }
  267.  
  268. int util_upload PROTO2(char *, path, FILE *, fp)
  269. {   
  270.   unsigned long pos;
  271.   unsigned bytes, first, tmax, sent_time;
  272.   char *fpath, buf[UBUF_SPACE];
  273.   UBUF *ub;
  274.   time_t t = time(NULL);
  275.   
  276.   fpath = util_abs_path(path);
  277.   
  278.   for(tmax = 1, sent_time = 0, pos = 0, first = 1; ; first = 0) {   
  279.     if((bytes = fread(buf,1,client_buf_len,fp)) || first) {
  280.       ub = client_interact(CC_UP_LOAD,pos, bytes, (unsigned char *)buf, 0,
  281.                (unsigned char *)NULLP);
  282.       if(client_trace && (udp_sent_time != sent_time)) {
  283.     sent_time = udp_sent_time;
  284.     if(client_buf_len == UBUF_SPACE)
  285.       fprintf(stderr,"\r%luk  ",1+(pos>>10));
  286.     else fprintf(stderr,"\r%lu   ",   pos     );
  287.     fflush(stderr);
  288.       }
  289.     } else
  290.       ub = client_interact(CC_INSTALL,pos,strlen(fpath), 
  291.                (unsigned char *)fpath+1, 0,
  292.                (unsigned char *)NULLP);
  293.     if(ub->cmd == CC_ERR) {    
  294.       fprintf(stderr,"uploading %s: %s\n",path,ub->buf);
  295.       free(fpath);
  296.       return(1); 
  297.     }   
  298.       
  299.     if(!bytes && !first) break;
  300.     pos += bytes;
  301.   }
  302.   
  303.   t = time(NULL) - t;
  304.   if(t == 0) t = 1;
  305.   if(client_trace) {
  306.     fprintf(stderr,"\r%luk : %s [%db/s] \n", 1+(pos>>10), path, pos/t);
  307.     fflush(stderr);
  308.   }
  309.   free(fpath);
  310.   return(0);
  311. }
  312.  
  313. static void util_get_env PROTO0((void))
  314. {
  315.   char *p;
  316.   
  317.   if(!(env_host = getenv("FSP_HOST"))) {
  318.     fputs("No FSP_HOST specified.\n",stderr);
  319.     exit(1);
  320.   }
  321.   if(!(env_port = getenv("FSP_PORT"))) {
  322.     fputs("No FSP_PORT specified.\n",stderr);
  323.     exit(1);
  324.   }
  325.   if(!(env_dir  = getenv("FSP_DIR"))) {
  326.     fputs("No FSP_DIR specified.\n",stderr);
  327.     exit(1);
  328.   }
  329.   if(!(env_myport = getenv("FSP_LOCALPORT"))) env_myport = "0";
  330.   if(!(env_passwd = getenv("FSP_PASSWORD"))) env_passwd = "\0";
  331.   client_trace  = !!getenv("FSP_TRACE");
  332.   if(p = getenv("FSP_BUF_SIZE")) client_buf_len = atoi(p);
  333.   else client_buf_len = UBUF_SPACE;
  334.   
  335.   if(client_buf_len > UBUF_SPACE) client_buf_len = UBUF_SPACE; 
  336.   client_net_len = htons(client_buf_len);
  337.   
  338.   if(p = getenv("FSP_DELAY")) target_delay = atol(p);
  339.   if(target_delay < MIN_DELAY) target_delay = MIN_DELAY;
  340.   
  341.   if(!(env_local_dir = getenv("FSP_LOCAL_DIR"))) env_local_dir=".";
  342.   
  343.   if(!(p = getenv("FSP_TIMEOUT"))) env_timeout = 4;
  344.   else env_timeout = atol(p);
  345. }
  346.  
  347. static void client_intr PROTO1(int, signum)
  348. {
  349.   switch(client_intr_state) {
  350.     case 0: exit(2);
  351.     case 1: client_intr_state = 2; break;
  352.     case 2: exit(3);
  353.   }
  354. }
  355.  
  356. void env_client PROTO0((void))
  357. {
  358.   util_get_env();
  359.   init_client(env_host,atoi(env_port),atoi(env_myport));
  360.   signal(SIGINT,client_intr);
  361. }
  362.  
  363. static DDLIST *ddroot = 0;
  364.  
  365. RDIR *util_opendir PROTO1(char *, path)
  366. {
  367.   char *fpath;
  368.   RDIRENT **dep;
  369.   DDLIST *ddp;
  370.   RDIR *rdirp;
  371.   
  372.   fpath = util_abs_path(path);
  373.   
  374.   for(ddp = ddroot; ddp; ddp = ddp->next)
  375.     if(!strcmp(ddp->path,fpath)) break;
  376.   
  377.   if(!ddp) {
  378.     if(!(dep = get_dir_blk(fpath))) return((RDIR *) 0);
  379.     ddp = (DDLIST *) malloc(sizeof(DDLIST));
  380.     ddp->dep_root = dep;
  381.     ddp->path = fpath;
  382.     ddp->ref_cnt = 0;
  383.     ddp->next = ddroot;
  384.     ddroot = ddp;
  385.   } else free(fpath);
  386.   
  387.   ddp->ref_cnt++;
  388.   
  389.   rdirp = (RDIR *) malloc(sizeof(RDIR));
  390.   rdirp->ddp = ddp;
  391.   rdirp->dep = ddp->dep_root;
  392.   return(rdirp);
  393. }
  394.  
  395. void util_closedir PROTO1(RDIR *, rdirp)
  396. {
  397.   rdirp->ddp->ref_cnt--;
  398.   free(rdirp);
  399. }
  400.  
  401. rdirent *util_readdir PROTO1(RDIR *, rdirp)
  402. {
  403.   static rdirent rde;
  404.   RDIRENT **dep;
  405.   
  406.   dep = rdirp->dep;
  407.   
  408.   if(!*dep) return((rdirent *) 0);
  409.   
  410.   rde.d_fileno = 10;
  411.   rde.d_reclen = 10;
  412.   rde.d_namlen = strlen((*dep)->name);
  413.   rde.d_name   = (*dep)->name;
  414.   rdirp->dep   = dep+1;
  415.   
  416.   return(&rde);
  417. }
  418.  
  419. static int util_split_path PROTO4(char *, path, char **, p1, char **, p2,
  420.                   char **, p3)
  421. {
  422.   char *s;
  423.   static char junk;
  424.   
  425.   *p1 = "/";
  426.   if(*path == '/') {
  427.     *p2 =  path;
  428.     *p3 = path+1;
  429.   } else {
  430.     *p2 = &junk;
  431.     *p3 = path;
  432.   }
  433.   
  434.   for(s = *p3; *s; s++) {
  435.     if(*s == '/') {
  436.       *p1 = path;
  437.       *p2 = s;
  438.       *p3 = s+1;
  439.     }
  440.   }
  441.   
  442.   if (**p3 == '\0') *p3 = ".";
  443.   return(1);
  444. }
  445.  
  446. int util_stat PROTO2(char *, path, struct stat *, sbuf)
  447. {
  448.   RDIR *drp;
  449.   RDIRENT **dep;
  450.   char *fpath, *ppath, *p1, *pfile;
  451.   
  452.   fpath = util_abs_path(path);
  453.   
  454.   if(!strcmp(fpath,env_dir)) {
  455.     ppath = fpath;
  456.     pfile = ".";
  457.   } else {
  458.     util_split_path(fpath,&ppath,&p1,&pfile);
  459.     *p1 = 0;
  460.   }
  461.   
  462.   if(drp = util_opendir(ppath)) {
  463.     for(dep = drp->dep; *dep; dep++) {
  464.       if(!strcmp((*dep)->name,pfile)) {
  465.     if((*dep)->type & RDTYPE_DIR) sbuf->st_mode = 0777 | S_IFDIR;
  466.     else sbuf->st_mode = 0666 | S_IFREG;
  467.           
  468.     if((*dep)->type & RDTYPE_DIR) sbuf->st_nlink  = 2;
  469.     else sbuf->st_nlink  = 1;
  470.     sbuf->st_uid = 0;
  471.     sbuf->st_gid = 0;
  472.     sbuf->st_size  = BB_READ4((*dep)->bb_size);
  473.     sbuf->st_atime = sbuf->st_mtime = 
  474.              sbuf->st_ctime = BB_READ4((*dep)->bb_time);
  475.     util_closedir(drp);
  476.     free(fpath);
  477.     return(0);
  478.       }
  479.     }
  480.     util_closedir(drp);
  481.   }
  482.   
  483.   free(fpath);
  484.   errno = ENOENT;
  485.   return(-1);
  486. }
  487.  
  488. int util_cd PROTO1(char *, p)
  489. {
  490.   char *fpath;
  491.   UBUF *ub;
  492.   DDLIST   *ddp;
  493.   
  494.   fpath = util_abs_path(p);
  495.   for(ddp = ddroot; ddp; ddp = ddp->next)
  496.     if(!strcmp(ddp->path,fpath)) break;
  497.   
  498.   if(!ddp && strcmp(p,".") && strcmp(p,"..")) {
  499.     ub = client_interact(CC_GET_DIR,0L, strlen(fpath),
  500.              (unsigned char *) fpath+1, 2,
  501.              (unsigned char *)&client_net_len);
  502.     if(ub->cmd == CC_ERR) {
  503.       free(fpath);
  504.       fprintf(stderr,"%s: %s\n",p, ub->buf);
  505.       errno = EACCES;
  506.       return(-1);
  507.     }
  508.   }
  509.   
  510.   if(env_dir_malloced) free(env_dir);
  511.   env_dir_malloced = 1;
  512.   env_dir = fpath;
  513.   return(0);
  514. }
  515.  
  516. /* Perform a cd, but don't verify path.  Assume the path has been
  517.  * pre-verified
  518.  */
  519. int util_cd2 PROTO1(char *, p)
  520. {
  521.   char *fpath;
  522.   
  523.   fpath = util_abs_path(p);
  524.   
  525.   if(env_dir_malloced) free(env_dir);
  526.   env_dir_malloced = 1;
  527.   env_dir = fpath;
  528.   return(0);
  529. }
  530.  
  531. #ifdef HAVE_ANSI_PROTO
  532. void util_process_file(char *path, int mode, void (*process_file)(),
  533.                int (*process_start_dir)(), void (*process_end_dir)(),
  534.                int level)
  535. #else
  536. void util_process_file(path, mode, process_file, process_start_dir,
  537.             process_end_dir, level)
  538.      char *path;
  539.      int mode, level;
  540.      void (*process_file)(), (*process_end_dir)();
  541.      int (*process_start_dir)();
  542. #endif
  543. {
  544.   struct stat sbuf;
  545.   RDIR *rdir;
  546.   struct rdirent *rde;
  547.   int pathlen;
  548.   char *newname;
  549.   u_long sum;
  550.  
  551.   if (util_stat(path, &sbuf) < 0) {
  552.     perror(path);
  553.     return;
  554.   }
  555.   
  556.   if (S_ISREG(sbuf.st_mode)) {
  557.     if(process_file) (*process_file)(path, &sbuf, mode, level);
  558.   } else if (S_ISDIR(sbuf.st_mode)) {
  559.     sum = mode;
  560.     if (process_start_dir && (*process_start_dir)(path, &sbuf, &sum) < 0)
  561.       fprintf(stderr, "skipping remote directory `%s'\n", path);
  562.     else {
  563.       if ((rdir = util_opendir(path))) {
  564.     pathlen = strlen(path);
  565.     while ((rde = util_readdir(rdir))) {
  566.       /* skip over "." and ".." */
  567.       if (rde->d_name[0] == '.' &&
  568.           (rde->d_name[1] == '\0'  ||
  569.            (rde->d_name[1] == '.' && rde->d_name[2] == '\0')))
  570.         continue;
  571.       newname = malloc(pathlen + rde->d_namlen + 2);
  572.  
  573.       strcpy(newname, path);
  574.       if(newname[pathlen-1] != '/') newname[pathlen] = '/';
  575.       else pathlen--;
  576.       strcpy(newname + pathlen + 1, rde->d_name);
  577.       util_process_file(newname, mode, process_file, process_start_dir,
  578.                 process_end_dir, level + 1);
  579.       free(newname);
  580.     }
  581.     util_closedir(rdir);
  582.       }
  583.       if(process_end_dir) (*process_end_dir)(path, mode, sum, level);
  584.     }
  585.   } else
  586.     fprintf(stderr, "remote file `%s' is not a file or directory!\n",path);
  587. /*  free(path); */
  588. }
  589.